/*
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package jchess;

import java.util.ArrayList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.*;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Rectangle;
import java.util.Collections;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;

/** Class representing the players moves, it's also checking
 * that the moves taken by player are correct.
 * All moves which was taken by current player are saving as List of Strings
 * The history of moves is printing in a table
 * @param game The current game
 */
public class Moves extends AbstractTableModel {

    private ArrayList<String> move = new ArrayList<String>();
    private ArrayList<String> moveNotacaoCurta = new ArrayList<String>();
    private int columns_num = 3;
    private int rows_num = 0;
    private String[] names = new String[]{Settings.lang("white"), Settings.lang("black")};
    private MyDefaultTableModel tableModel;
    private JScrollPane scrollPane;
    private JTable table;
    private boolean enterBlack = false;
    private Game game;
    // mudei
    private MyDefaultTableModel tableModelCapturadas;
    private JScrollPane scrollPaneCapturadas;
    private JTable tableCapturadas;
    private TableCellRenderer tableRendererCapturadas;
    private int colunasTabelaCapturadas = 3;
    private int linhasTabelaCapturadas = 0;
    private int linhaBrancasCapturadas = 0;
    private int linhaPretasCapturadas = 0;

    Moves(Game game) {
        super();
        this.tableModel = new MyDefaultTableModel();
        this.table = new JTable(this.tableModel);
        this.scrollPane = new JScrollPane(this.table);
        this.scrollPane.setMaximumSize(new Dimension(100, 100));
        this.table.setMinimumSize(new Dimension(100, 100));
        this.game = game;

        this.tableModel.addColumn(this.names[0]);
        this.tableModel.addColumn(this.names[1]);
        this.addTableModelListener(null);
        this.tableModel.addTableModelListener(null);
        this.scrollPane.setAutoscrolls(true);

        // mudei
        //super();
        this.tableModelCapturadas = new MyDefaultTableModel();
        this.tableCapturadas = new JTable(this.tableModelCapturadas);
        this.scrollPaneCapturadas = new JScrollPane(this.tableCapturadas);
        this.scrollPaneCapturadas.setMaximumSize(new Dimension(100, 100));
        this.tableCapturadas.setMaximumSize(new Dimension(100, 100));
        //this.game = game;

        this.tableModelCapturadas.addColumn("Brancas");
        this.tableModelCapturadas.addColumn("Pretas");
        //this.addTableModelListener(null);
        this.tableModelCapturadas.addTableModelListener(null);
        this.scrollPaneCapturadas.setAutoscrolls(true);

        this.tableRendererCapturadas = new ImageRenderer();
        this.tableCapturadas.getColumnModel().getColumn(0).setCellRenderer(tableRendererCapturadas);
        this.tableCapturadas.getColumnModel().getColumn(1).setCellRenderer(tableRendererCapturadas);

        this.tableCapturadas.setRowHeight(58);
    }

    public void draw() {
    }

    @Override
    public String getValueAt(int x, int y) {
        return this.getMove().get((y * 2) - 1 + (x - 1));
    }

    @Override
    public int getRowCount() {
        return this.rows_num;
    }

    @Override
    public int getColumnCount() {
        return this.columns_num;
    }

    private void addRow() {
        this.tableModel.addRow(new String[2]);
    }

    // mudei
    private void addRowImage() {
        this.tableModelCapturadas.addRow(new ImageIcon[2]);
    }

    public void addCastling(String move) {
        this.getMove().remove(this.getMove().size() - 1);//remove last element (move of Rook)
        this.getMoveNotacaoCurta().remove(this.getMoveNotacaoCurta().size() - 1);
        if (!this.enterBlack) {
            this.tableModel.setValueAt(move, this.tableModel.getRowCount() - 1, 1);//replace last value
        } else {
            this.tableModel.setValueAt(move, this.tableModel.getRowCount() - 1, 0);//replace last value
        }
        this.getMove().add(move);//add new move (O-O or O-O-O)
        this.getMoveNotacaoCurta().add(move);
    }

    @Override
    public boolean isCellEditable(int a, int b) {
        return false;
    }

    /** Method of adding new moves to the table
     * @param str String which in is saved player move
     */
    private void addMove2Table(String str) {
        if (!this.enterBlack) {
            this.addRow();
            this.tableModel.setValueAt(str, rows_num, 0);
        } else {
            this.tableModel.setValueAt(str, rows_num, 1);
            this.rows_num += 1;
        }
        this.enterBlack = !this.enterBlack;
        this.table.scrollRectToVisible(table.getCellRect(table.getRowCount() - 1, 0, true));//scroll to down
    }

    // mudei
    private void addPiece2Table(Piece peca) {
        if (peca.player.color == Player.colors.white) { // se a peça capturada for branca
            if (linhaBrancasCapturadas == linhasTabelaCapturadas) {
                this.addRowImage();
                this.tableModelCapturadas.setValueAt(peca.getImageIcon(), linhaBrancasCapturadas, 0);
                linhaBrancasCapturadas++;
                linhasTabelaCapturadas++;

            } else {
                this.tableModelCapturadas.setValueAt(peca.getImageIcon(), linhaBrancasCapturadas, 0);
                linhaBrancasCapturadas++;
            }
        } else { // se a peça capturada for preta
            if (linhaPretasCapturadas == linhasTabelaCapturadas) {
                this.addRowImage();
                this.tableModelCapturadas.setValueAt(peca.getImageIcon(), linhaPretasCapturadas, 1);
                linhaPretasCapturadas++;
                linhasTabelaCapturadas++;
            } else {
                this.tableModelCapturadas.setValueAt(peca.getImageIcon(), linhaPretasCapturadas, 1);
                linhaPretasCapturadas++;
            }
        }
        this.tableCapturadas.scrollRectToVisible(tableCapturadas.getCellRect(linhasTabelaCapturadas, 0, true));
    }

    /** Method of adding new move
     * @param move String which in is capt player move
     */
    public void addMove(String move) {
        if (isMoveCorrect(move)) {
            this.getMove().add(move);
            this.addMove2Table(move);
        }
    }

    public void addMove(Square begin, Square end) {
        this.addMove(begin, end, false);
    }

    private String pozXtoStr(int pozX, boolean upsideDown) {
        if (upsideDown) {
            pozX = (pozX < 4) ? (pozX + (2 * (4 - pozX))) : (pozX - 2 * (pozX - 4));
            pozX -= 1;
        }
        return Character.toString((char) (pozX + 97));//add letter of Square from which move was made
    }

    private String pozYtoStr(int pozY, boolean upsideDown) {
        if (!upsideDown) {
            pozY = (pozY < 4) ? (pozY + (2 * (4 - pozY))) : (pozY - 2 * (pozY - 4));
            pozY -= 1;
        }
        return Integer.toString(pozY + 1);//add number of Square from which move was made
    }

    private int strToPozY(String str, boolean upsideDown) {
        Integer char_int = new Integer(new Character(str.charAt(0)).toString());
        if (!upsideDown) {
            int tmp = (char_int < 4) ? (char_int + (2 * (4 - char_int))) : (char_int - 2 * (char_int - 4));
            char_int = (tmp);
        }
        return char_int;
    }

    private int strToPozY(String str) {
        return this.strToPozY(str, false);
    }

    private int strToPozX(char letraColuna) {
        return letraColuna - 97;
    }

    public void addMove(Square begin, Square end, boolean upsideDown) {
        Piece pecaAMover = begin.getPiece();
        String locMove = begin.getPiece().getSymbol();
        String locMoveNotacaoCurta = begin.getPiece().getSymbol();
        Boolean envolveCaptura = false;
        Piece pecaCapturada = null;

        locMove += this.pozXtoStr(begin.getPozX(), upsideDown) + this.pozYtoStr(begin.getPozY(), upsideDown);

        if (!pecaAMover.getName().equals("Pawn")) {
            List list = pecaAMover.outrasQuePodemIrParaAMesmaCasa(end);
            if (list.isEmpty()) {
                // nao faz nada
            } else if (list.size() == 1) {
                if (!pecaAMover.temOutraDeMesmoTipoECorNaColuna(begin)) {
                    locMoveNotacaoCurta += this.pozXtoStr(begin.getPozX(), upsideDown);
                } else {
                    locMoveNotacaoCurta += this.pozYtoStr(begin.getPozY(), upsideDown);
                }
            } else {
                locMoveNotacaoCurta += this.pozXtoStr(begin.getPozX(), upsideDown) + this.pozYtoStr(begin.getPozY(), upsideDown);
            }
        }
        if (end.getPiece() != null) {
            if (pecaAMover.getName().equals("Pawn")) {
                // se a peça que captura for um peão, insere a coluna A..H de origem
                locMoveNotacaoCurta += this.pozXtoStr(begin.getPozX(), upsideDown);
            }
            locMove += "x";//take down opponent piece
            locMoveNotacaoCurta += "x";//take down opponent piece

            envolveCaptura = true;
            pecaCapturada = end.getPiece();
        } else { // na alg curta nao usa o -, pq nao tem casa de origem
            locMove += "-";//normal move
        }

        locMove += this.pozXtoStr(end.getPozX(), upsideDown) + this.pozYtoStr(end.getPozY(), upsideDown);
        locMoveNotacaoCurta += this.pozXtoStr(end.getPozX(), upsideDown) + this.pozYtoStr(end.getPozY(), upsideDown);

        if (begin.getPiece().getSymbol().equals("") && begin.getPozX() - end.getPozX() != 0 && end.getPiece() == null) {
            locMove += "(e.p)";//pawn take down opponent en passant
            locMoveNotacaoCurta += "(e.p)";//pawn take down opponent en passant
        }
        if ((!this.enterBlack && this.game.chessboard.kingBlack.isChecked())
                || (this.enterBlack && this.game.chessboard.kingWhite.isChecked())) {//if checked

            if ((!this.enterBlack && this.game.chessboard.kingBlack.isCheckmatedOrStalemated() == 1)
                    || (this.enterBlack && this.game.chessboard.kingWhite.isCheckmatedOrStalemated() == 1)) {//check if checkmated
                locMove += "#";//check mate
                locMoveNotacaoCurta += "#";//check mate
            } else {
                locMove += "+";//check
                locMoveNotacaoCurta += "+";//check
            }
        }

        this.getMove().add(locMove);
        this.getMoveNotacaoCurta().add(locMoveNotacaoCurta);
        this.addMove2Table(locMoveNotacaoCurta);

        if (envolveCaptura) {
            // limpar a tabela de capturadas
            for (int i = this.tableModelCapturadas.getRowCount() - 1; i >= 0; i--) {
                this.tableModelCapturadas.removeRow(i);
            }
            linhasTabelaCapturadas = 0;
            linhaBrancasCapturadas = 0;
            linhaPretasCapturadas = 0;

            // readicionar as capturadas
            this.game.pecasCapturadas.add(pecaCapturada);
            Collections.sort(this.game.pecasCapturadas);

            for (Piece peca : this.game.pecasCapturadas) {
                if (peca.player.color == Player.colors.white) {
                    //System.out.print(peca + ", ");
                    addPiece2Table(peca);
                }
            }

            for (Piece peca : this.game.pecasCapturadas) {
                if (peca.player.color == Player.colors.black) {
                    //System.out.print(peca + ", ");
                    addPiece2Table(peca);
                }
            }
        }
        this.scrollPane.scrollRectToVisible(new Rectangle(0, this.scrollPane.getHeight() - 2, 1, 1));
        this.scrollPaneCapturadas.scrollRectToVisible(new Rectangle(0, this.scrollPaneCapturadas.getHeight() - 2, 1, 1));
    }

    public JScrollPane getScrollPane() {
        return this.scrollPane;
    }

    public JScrollPane getScrollPaneCapturadas() {
        return this.scrollPaneCapturadas;
    }

    public ArrayList<String> getMoves() {
        return this.getMove();
    }

    public ArrayList<String> getMovesNotacaoCurta() {
        return this.getMoveNotacaoCurta();
    }

    /** Method with is checking is the move is correct
     * @param move String which in is capt player move
     * @return boolean 1 if the move is correct, else 0
     */
    static public boolean isMoveCorrect(String move) {
        if (move.equals("O-O") || move.equals("O-O-O")) {
            return true;
        }
        int from = 0;
        int sign = move.charAt(from);//get First
        switch (sign) { //if sign of piece, get next
            case 66: // B like Bishop
            case 75: // K like King
            case 78: // N like Knight
            case 81: // Q like Queen
            case 82:
                from = 1;
                break; // R like Rook
        }
        sign = move.charAt(from);
        System.out.println(sign);
        if (sign < 97 || sign > 104) {
            return false;
        }
        sign = move.charAt(from + 1);
        if (sign < 49 || sign > 56) {
            return false;
        }
        sign = move.charAt(from + 2);
        if (sign != 45 && sign != 120) {
            return false;
        }
        sign = move.charAt(from + 3);
        if (sign < 97 || sign > 104) {
            return false;
        }
        sign = move.charAt(from + 4);
        if (sign < 49 || sign > 56) {
            return false;
        }
        return true;
    }

    public void addMoves(ArrayList<String> list) {
        for (String singleMove : list) {
            if (isMoveCorrect(singleMove)) {
                this.addMove(singleMove);
            }
        }
    }

    /** Method of getting the moves in string
     *  @return str String which in is capt player move
     */
    public String getMovesInString() {
        int n = 1;
        int i = 0;
        String str = new String();
        for (String locMove : this.getMoves()) {
            if (i % 2 == 0) {
                str += n + ". ";
                n += 1;
            }
            str += locMove + " ";
            i += 1;
        }
        return str;
    }

    public String getMovesInStringNotacaoCurta() {
        int n = 1;
        int i = 0;
        String str = new String();
        for (String locMove : this.getMovesNotacaoCurta()) {
            if (i % 2 == 0) {
                str += n + ". ";
                n += 1;
            }
            str += locMove + " ";
            i += 1;
        }
        return str;
    }

    public String getMovesInStringPersonalizado(ArrayList<String> movimentos) {
        int n = 1;
        int i = 0;
        String str = new String();
        for (String locMove : movimentos) {
            if (i % 2 == 0) {
                str += n + ". ";
                n += 1;
            }
            str += locMove + " ";
            i += 1;
        }
        return str;
    }

    /** Method to set all moves from String with validation test (usefoul for network game)
     *  @param  moves String to set in String like PGN with full-notation format
     */
    public void setMoves(String moves) {
        int from = 0;
        int to = 0;
        int n = 1;
        ArrayList<String> tempArray = new ArrayList();
        int tempStrSize = moves.length() - 1;
        while (true) {
            from = moves.indexOf(" ", from);
            to = moves.indexOf(" ", from + 1);

            try {
                tempArray.add(moves.substring(from + 1, to).trim());
            } catch (java.lang.StringIndexOutOfBoundsException exc) {
                System.out.println("error parsing file to load: " + exc);
                break;
            }
            if (n % 2 == 0) {
                from = moves.indexOf(".", to);
                if (from < to) {
                    break;
                }
            } else {
                from = to;
            }
            n += 1;
            if (from > tempStrSize || to > tempStrSize) {
                break;
            }
        }
        // retirado temporariamente (voltar depois)
        /*for (String locMove : tempArray) {//test if moves are written correctly
        if (!Moves.isMoveCorrect(locMove.trim())) {//if not
        JOptionPane.showMessageDialog(this.game, Settings.lang("invalid_file_to_load") + getMove());
        return;//show message and finish reading game
        }
        }*/
        boolean canMove = false;
        boolean vezDasBrancas = true;

        for (String locMove : tempArray) {
            if (locMove.equals("O-O-O") || locMove.equals("O-O")) { //if castling
                int[] values = new int[4];
                if (locMove.equals("O-O-O")) {
                    if (this.game.getActivePlayer().color == Player.colors.black) { //if black turn
                        values = new int[]{4, 0, 2, 0};//move value for castling (King move)
                    } else {
                        values = new int[]{4, 7, 2, 7};//move value for castling (King move)
                    }
                } else if (locMove.equals("O-O")) { //if short castling
                    if (this.game.getActivePlayer().color == Player.colors.black) {//if black turn
                        values = new int[]{4, 0, 6, 0};//move value for castling (King move)
                    } else {
                        values = new int[]{4, 7, 6, 7};//move value for castling (King move)
                    }
                }
                canMove = this.game.simulateMove(values[0], values[1], values[2], values[3]);
                if (!canMove) {//if move is illegal
                    JOptionPane.showMessageDialog(this.game, Settings.lang("illegal_move_on") + locMove);
                    return;//finish reading game and show message
                }
                continue;
            }
            from = 0;
            int num = locMove.charAt(from);
            if (num <= 90 && num >= 65) {
                from = 1;
            }
            /*int xFrom = locMove.charAt(from) - 97;//from ASCII
            int yFrom = strToPozY(Character.toString(locMove.charAt(from + 1)));
            int xTo = locMove.charAt(from + 3) - 97;//from ASCII
            int yTo = strToPozY(Character.toString(locMove.charAt(from + 4)));*/

            int xFrom = encontraCasaOrigem(locMove, vezDasBrancas).getPozX();
            int yFrom = encontraCasaOrigem(locMove, vezDasBrancas).getPozY();
            int xTo = encontraCasaDestino(locMove).getPozX();
            int yTo = encontraCasaDestino(locMove).getPozY();

            canMove = this.game.simulateMove(xFrom, yFrom, xTo, yTo);
            if (!canMove) {//if move is illegal
                JOptionPane.showMessageDialog(this.game, Settings.lang("illegal_move_on") + locMove);
                return;//finish reading game and show message
            }
            vezDasBrancas = !vezDasBrancas;
        }
    }

    private Square encontraCasaOrigem(String string, boolean vezDasBrancas) {
        int xFrom = -1;
        int yFrom = -1;

        if (movimentoDePeao(string)) {
            xFrom = strToPozX(string.charAt(0));

            if (envolveCaptura(string)) {
                char fileira = string.charAt(3);
                yFrom = strToPozY(Character.toString(fileira)) + (vezDasBrancas ? 1 : -1);
            } else {
                for (int fileira = 0; fileira < 8; fileira++) {
                    Piece pecaEncontrada = this.game.chessboard.squares[xFrom][fileira].getPiece();

                    if (pecaEncontrada != null
                            && pecaEncontrada.getName().equals("Pawn")
                            && pecaEncontrada.player.color == (vezDasBrancas ? Player.colors.white : Player.colors.black)) {
                        yFrom = fileira;
                        break;
                    }
                }
            }
        } else { // se nao for movimento de peao
            if (grauAmbiguidade(string) == 0) {
                boolean para = false;
                for (int x = 0; x < 8; x++) {
                    for (int y = 0; y < 8; y++) {
                        Piece pecaEncontrada = this.game.chessboard.squares[x][y].getPiece();

                        if (pecaEncontrada != null
                                && pecaEncontrada.getSymbol().equals(string.substring(0, 1))
                                && pecaEncontrada.player.color == (vezDasBrancas ? Player.colors.white : Player.colors.black)) {
                            xFrom = x;
                            yFrom = y;

                            para = true;
                            break;
                        }
                    }
                    if (para) {
                        break;
                    }
                }
            } else if (grauAmbiguidade(string) == 1) {
                if (ambiguoParaColuna(string)) {
                    char coluna = string.charAt(1); // 2o carac, ex.: Nde5 (cavalo da coluna D para a casa e5)
                    xFrom = strToPozX(coluna);

                    for (int fileira = 0; fileira < 8; fileira++) {
                        Piece pecaEncontrada = this.game.chessboard.squares[xFrom][fileira].getPiece();

                        if (pecaEncontrada != null
                                && pecaEncontrada.getSymbol().equals(string.substring(0, 1))
                                && pecaEncontrada.player.color == (vezDasBrancas ? Player.colors.white : Player.colors.black)) {
                            yFrom = fileira;

                            break;
                        }
                    }
                } else if (ambiguoParaFileira(string)) {
                    char fileira = string.charAt(1);// 2o carac, ex.: N1e5 (cavalo da fileira 1 para a casa e5)
                    yFrom = Integer.parseInt(Character.toString(fileira));

                    for (int coluna = 0; coluna < 8; coluna++) {
                        Piece pecaEncontrada = this.game.chessboard.squares[coluna][yFrom].getPiece();

                        if (pecaEncontrada != null
                                && pecaEncontrada.getSymbol().equals(string.substring(0, 1))
                                && pecaEncontrada.player.color == (vezDasBrancas ? Player.colors.white : Player.colors.black)) {
                            xFrom = coluna;

                            break;
                        }
                    }
                }
            } else if (grauAmbiguidade(string) == 2) {
                // no caso de ser ambíguo para ambos, a casa de origem ja estah explicita no proprio movimento
                char coluna = string.charAt(1);
                char fileira = string.charAt(2);

                xFrom = strToPozX(coluna);
                yFrom = strToPozY(Character.toString(fileira));
            }
        }

        return new Square(xFrom, yFrom, null);
    }

    private Square encontraCasaDestino(String string) {
        int xTo = strToPozX(string.substring(string.length() - 2, string.length() - 1).charAt(0)); // penúltimo caractere
        int yTo = strToPozY(string.substring(string.length() - 1, string.length())); // último caractere

        return new Square(xTo, yTo, null);
    }

    private boolean movimentoDePeao(String string) {
        char inicial = string.charAt(0);
        return (inicial >= 'a' && inicial <= 'h'); // entre "a" e "h" (representam as colunas)
    }

    private boolean envolveCaptura(String string) {
        return string.contains("x");
    }

    // 0 - não é ambiguo
    // 1 - ambiguo de coluna ou de linha
    // 2 - ambiguo de ambos
    private int grauAmbiguidade(String string) {
        if (movimentoDePeao(string)) {
            return 0; // peoes nao tem movimentos ambiguos
        } else if (ambiguoParaColuna(string) && !ambiguoParaFileira(string)) {
            return 1;
        } else if (ambiguoParaFileira(string) && !ambiguoParaColuna(string)) {
            return 1;
        } else if (ambiguoParaColuna(string) && ambiguoParaFileira(string)) {
            return 2;
        } else {
            return 0;
        }
    }

    private boolean ambiguoParaColuna(String string) {
        int qtdeVezesApareceColuna = 0;
        for (int i = 0; i < string.length(); i++) {
            if (string.charAt(i) >= 'a' && string.charAt(1) <= 'h') {
                qtdeVezesApareceColuna++;
            }
        }
        return (qtdeVezesApareceColuna > 1);
        // A coluna vai sempre aparecer pelo menos 1 vez por causa da casa destino.
        // Se aparecer mais de uma vez, entao o movimento eh ambiguo para coluna.
    }

    private boolean ambiguoParaFileira(String string) {
        int qtdeVezesApareceFileira = 0;
        for (int i = 0; i < string.length(); i++) {
            if (string.charAt(i) >= '1' && string.charAt(1) <= '8') {
                qtdeVezesApareceFileira++;
            }
        }
        return (qtdeVezesApareceFileira > 1);
        // A fileira vai sempre aparecer pelo menos 1 vez por causa da casa destino.
        // Se aparecer mais de uma vez, entao o movimento eh ambiguo para fileira.
    }

    public void setMovesPersonalizado(String moves, int numeroJogada) {
        int from = 0;
        int to = 0;
        int n = 1;
        ArrayList<String> tempArray = new ArrayList();
        int tempStrSize = moves.length() - 1;
        while (true && numeroJogada > tempArray.size()) {
            from = moves.indexOf(" ", from);
            to = moves.indexOf(" ", from + 1);
            //System.out.println(from+">"+to);
            try {
                tempArray.add(moves.substring(from + 1, to).trim());
            } catch (java.lang.StringIndexOutOfBoundsException exc) {
                System.out.println("error parsing file to load: " + exc);
                break;
            }
            if (n % 2 == 0) {
                from = moves.indexOf(".", to);
                if (from < to) {
                    break;
                }
            } else {
                from = to;
            }
            n += 1;
            if (from > tempStrSize || to > tempStrSize) {
                break;
            }
        }

        for (String locMove : tempArray) {//test if moves are written correctly
            if (!Moves.isMoveCorrect(locMove.trim())) {//if not
                JOptionPane.showMessageDialog(this.game, Settings.lang("invalid_file_to_load") + getMove());
                return;//show message and finish reading game
            }
        }
        boolean canMove = false;
        for (String locMove : tempArray) {
            if (locMove.equals("O-O-O") || locMove.equals("O-O")) { //if castling
                int[] values = new int[4];
                if (locMove.equals("O-O-O")) {
                    if (this.game.getActivePlayer().color == Player.colors.black) { //if black turn
                        values = new int[]{4, 0, 2, 0};//move value for castling (King move)
                    } else {
                        values = new int[]{4, 7, 2, 7};//move value for castling (King move)
                    }
                } else if (locMove.equals("O-O")) { //if short castling
                    if (this.game.getActivePlayer().color == Player.colors.black) {//if black turn
                        values = new int[]{4, 0, 6, 0};//move value for castling (King move)
                    } else {
                        values = new int[]{4, 7, 6, 7};//move value for castling (King move)
                    }
                }
                canMove = this.game.simulateMove(values[0], values[1], values[2], values[3]);
                if (!canMove) {//if move is illegal
                    JOptionPane.showMessageDialog(this.game, Settings.lang("illegal_move_on") + locMove);
                    return;//finish reading game and show message
                }
                continue;
            }
            from = 0;
            int num = locMove.charAt(from);
            if (num <= 90 && num >= 65) {
                from = 1;
            }
            int xFrom = locMove.charAt(from) - 97;//from ASCII
            int yFrom = strToPozY(Character.toString(locMove.charAt(from + 1)));
            //int yFrom = locMove.charAt(from+1)-49;//from ASCII
            int xTo = locMove.charAt(from + 3) - 97;//from ASCII
            int yTo = strToPozY(Character.toString(locMove.charAt(from + 4)));
            //int yTo   = locMove.charAt(from+4)-49;//from ASCII
            canMove = this.game.simulateMove(xFrom, yFrom, xTo, yTo);
            if (!canMove) {//if move is illegal
                JOptionPane.showMessageDialog(this.game, Settings.lang("illegal_move_on") + locMove);
                return;//finish reading game and show message
            }
        }
    }

    public int quantidadeDeJogadas(String moves) {
        int from = 0;
        int to = 0;
        int n = 1;
        ArrayList<String> tempArray = new ArrayList();
        int tempStrSize = moves.length() - 1;
        while (true) {
            from = moves.indexOf(" ", from);
            to = moves.indexOf(" ", from + 1);
            //System.out.println(from+">"+to);
            try {
                tempArray.add(moves.substring(from + 1, to).trim());
            } catch (java.lang.StringIndexOutOfBoundsException exc) {
                System.out.println("error parsing file to load: " + exc);
                break;
            }
            if (n % 2 == 0) {
                from = moves.indexOf(".", to);
                if (from < to) {
                    break;
                }
            } else {
                from = to;
            }
            n += 1;
            if (from > tempStrSize || to > tempStrSize) {
                break;
            }
        }
        return tempArray.size();
    }

    /**
     * @return the move
     */
    public ArrayList<String> getMove() {
        return move;
    }

    /**
     * @param move the move to set
     */
    public void setMove(ArrayList<String> move) {
        this.move = move;
    }

    public ArrayList<String> getMoveNotacaoCurta() {
        return moveNotacaoCurta;
    }

    public void setMoveNotacaoCurta(ArrayList<String> moveNotacaoCurta) {
        this.moveNotacaoCurta = moveNotacaoCurta;
    }
}
/*
 * Overriding DefaultTableModel and  isCellEditable method
 * (history cannot be edited by player)
 */

class MyDefaultTableModel extends DefaultTableModel {

    MyDefaultTableModel() {
        super();
    }

    @Override
    public boolean isCellEditable(int a, int b) {
        return false;
    }
}